package server

import (
	"encoding/json"
	"errors"
	"time"

	"github.com/mitchellh/mapstructure"
)

// ResBook 书籍资源模型
// 对应数据库表res_book
// 包含书籍的基本信息、状态和统计信息
type ResBook struct {
	ID             uint      `json:"id" gorm:"primarykey"`                                                     // 主键ID
	Title          string    `json:"title"`                                                                    // 书籍标题
	Image          string    `json:"image"`                                                                    // 封面图片URL
	Category       string    `json:"category"`                                                                 // 分类名称
	Author         string    `json:"author"`                                                                   // 作者名称
	ChapterCnt     int       `mapstructure:"chapter_cnt" json:"chapter_cnt" gorm:"chapter_cnt"`                // 总章节数
	Intro          string    `json:"intro"`                                                                    // 书籍简介
	Flag           int       `json:"flag"`                                                                     // 状态标记(位运算)
	Free           int       `json:"free"`                                                                     // 是否免费(0/1)
	Value          int       `json:"value"`                                                                    // 附加数值
	FreeChapterCnt int       `mapstructure:"free_chapter_cnt" json:"free_chapter_cnt" gorm:"free_chapter_cnt"` // 免费章节数
	ChapterCost    int       `mapstructure:"chapter_cost" json:"chapter_cost" gorm:"chapter_cost"`             // 章节价格(积分)
	Tags           string    `json:"tags"`                                                                     // 标签(逗号分隔)
	RecentChapter  string    `mapstructure:"recent_chapter" json:"recent_chapter" gorm:"recent_chapter"`       // 最新章节
	CatalogLink    string    `mapstructure:"catalog_link" json:"catalog_link" gorm:"catalog_link"`             // 目录链接
	WordsCnt       int       `mapstructure:"words_cnt" json:"words_cnt" gorm:"words_cnt"`                      // 总字数
	Status         int       `json:"status"`                                                                   // 状态(0:下架 1:上架)
	CreateTime     time.Time `mapstructure:"create_time" json:"create_time" gorm:"create_time"`                // 创建时间
	UpdateTime     time.Time `mapstructure:"update_time" json:"update_time" gorm:"create_time"`                // 更新时间
}

// TableName 指定GORM使用的表名
// 返回值:
//
//	string - 数据库表名
func (b *ResBook) TableName() string {
	return "res_book"
}

// AliasBook ResBook的类型别名
// 用于JSON反序列化时避免递归调用
type AliasBook ResBook

// TempBook 临时书籍结构体
// 用于处理JSON中的时间格式转换
// 包含:
//
//	AliasBook - 书籍基础字段
//	CreateTime - 字符串格式的创建时间
//	UpdateTime - 字符串格式的更新时间
type TempBook struct {
	AliasBook
	CreateTime string `mapstructure:"create_time" json:"create_time"`
	UpdateTime string `mapstructure:"update_time" json:"update_time"`
}

// UnmarshalJSON 自定义JSON反序列化方法
// 主要处理时间格式转换问题
// 参数:
//
//	data - 原始JSON数据
//
// 返回值:
//
//	error - 错误信息
func (b *ResBook) UnmarshalJSON(data []byte) error {
	// 检查空指针
	if b == nil {
		return errors.New("json.RawMessage: UnmarshalJSON on nil pointer")
	}

	// 使用临时结构体接收原始JSON数据
	tmpBook := TempBook{
		AliasBook: (AliasBook)(*b), // *b 是指针解引用，获取ResBook结构体的值，然后转换为AliasBook类型
	}

	// 反序列化到临时结构体
	if err := json.Unmarshal(data, &tmpBook); err != nil {
		return err
	}

	// 转换时间格式(北京时间)
	l, _ := time.LoadLocation("Asia/Shanghai")
	b.CreateTime, _ = time.ParseInLocation("2006-01-02T15:04:05", tmpBook.CreateTime, l)
	// 解析更新时间字符串，格式为"2006-01-02T15:04:05"，使用上海时区
	b.UpdateTime, _ = time.ParseInLocation("2006-01-02T15:04:05", tmpBook.UpdateTime, l)

	return nil
}

// UndecodeMap 从map结构解码数据
// 主要用于Elasticsearch等场景的结果转换
// 参数:
//
//	o - 包含书籍数据的map
//
// 返回值:
//
//	error - 错误信息
func (b *ResBook) UndecodeMap(o interface{}) error {
	// 类型断言转换为map
	m := o.(map[string]interface{})

	// 提取时间字段并删除(需要特殊处理)
	createTime := m["create_time"].(string)
	updateTime := m["update_time"].(string)
	delete(m, "create_time")
	delete(m, "update_time")

	// 使用mapstructure库解码剩余字段
	if err := mapstructure.Decode(m, b); err != nil {
		return err
	}

	// 转换时间格式(北京时间)
	l, _ := time.LoadLocation("Asia/Shanghai")
	b.CreateTime, _ = time.ParseInLocation("2006-01-02T15:04:05", createTime, l)
	b.UpdateTime, _ = time.ParseInLocation("2006-01-02T15:04:05", updateTime, l)

	return nil
}
